package middlewares

import (
	"context"
	pb "kitest1"
	"os"
	"strconv"
	"time"

	"github.com/go-kit/kit/log"
	"github.com/go-kit/kit/metrics"
	"github.com/go-kit/kit/sd"
	"github.com/go-kit/kit/sd/consul"
	"github.com/hashicorp/consul/api"
)

// metricMiddleware 定义监控中间件，嵌入Service
// 新增监控指标项：requestCount和requestLatency
type metricMiddleware struct {
	pb.CalcServer
	log            log.Logger
	requestCount   metrics.Counter
	requestLatency metrics.Histogram
}

func (mw metricMiddleware) Add(ctx context.Context, in *pb.CalcRequest) (ret *pb.CalcResponse, err error) {

	defer func(beign time.Time) {
		lvs := []string{"method", "Add"}
		mw.requestCount.With(lvs...).Add(1)
		mw.requestLatency.With(lvs...).Observe(time.Since(beign).Seconds())
	}(time.Now())

	ret, err = mw.CalcServer.Add(ctx, in)
	return
}

func (mw metricMiddleware) Sub(ctx context.Context, in *pb.CalcRequest) (ret *pb.CalcResponse, err error) {

	defer func(beign time.Time) {
		lvs := []string{"method", "Subtract"}
		mw.requestCount.With(lvs...).Add(1)
		mw.requestLatency.With(lvs...).Observe(time.Since(beign).Seconds())
	}(time.Now())

	ret, err = mw.CalcServer.Sub(ctx, in)
	return
}

func (mw metricMiddleware) Mul(ctx context.Context, in *pb.CalcRequest) (ret *pb.CalcResponse, err error) {

	defer func(beign time.Time) {
		lvs := []string{"method", "Multiply"}
		mw.requestCount.With(lvs...).Add(1)
		mw.requestLatency.With(lvs...).Observe(time.Since(beign).Seconds())
	}(time.Now())

	ret, err = mw.CalcServer.Mul(ctx, in)
	return
}

func (mw metricMiddleware) Div(ctx context.Context, in *pb.CalcRequest) (ret *pb.CalcResponse, err error) {

	defer func(beign time.Time) {
		lvs := []string{"method", "Divide"}
		mw.requestCount.With(lvs...).Add(1)
		mw.requestLatency.With(lvs...).Observe(time.Since(beign).Seconds())
	}(time.Now())

	ret, err = mw.CalcServer.Div(ctx, in)
	return
}

func (mw metricMiddleware) HealCheck(ctx context.Context, in *pb.HealReQuest) (ret *pb.HealResponse, err error) {

	defer func(begin time.Time) {
		lvs := []string{"method", "HealthCheck"}
		mw.requestCount.With(lvs...).Add(1)
		mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
	}(time.Now())
	// mw.log.Log("HealCheck", "run")
	ret, err = mw.CalcServer.HealCheck(ctx, in)
	return
}

func NewMetricMiddle(next pb.CalcServer, log log.Logger, requestCount metrics.Counter, requestLatency metrics.Histogram) pb.CalcServer {
	return metricMiddleware{next, log, requestCount, requestLatency}
}

func Register(consulHost, consulPort, svcHost, svcPort string, logger log.Logger) (registar sd.Registrar) {

	// 创建Consul客户端连接
	var client consul.Client
	{
		consulCfg := api.DefaultConfig()
		consulCfg.Address = consulHost + ":" + consulPort
		consulClient, err := api.NewClient(consulCfg)
		if err != nil {
			logger.Log("create consul client error:", err)
			os.Exit(1)
		}

		client = consul.NewClient(consulClient)
	}

	// 设置Consul对服务健康检查的参数
	check := api.AgentServiceCheck{
		HTTP:     "http://" + svcHost + ":" + svcPort + "/healcheck",
		Interval: "10s",
		Timeout:  "1s",
		Notes:    "Consul check service health status.",
	}

	port, _ := strconv.Atoi(svcPort)

	//设置微服务想Consul的注册信息
	reg := api.AgentServiceRegistration{
		ID:      "test4calc_1",
		Name:    "test4",
		Address: svcHost,
		Port:    port,
		Tags:    []string{"test4", "jack"},
		Check:   &check,
	}

	// 执行注册
	registar = consul.NewRegistrar(client, &reg, logger)
	return
}
